Release 10.1A: OpenEdge Application Server:
Developing AppServer Applications


Managing conflicts between client and AppServer

All AppServer transactions (normal or automatic) occur in a context that is separate and distinct from the client. One way of understanding this is that if both a client and an AppServer access the same database, each one accesses the database as a different user, whether or not the client is connected to the AppServer. As a result, any combination of AppServer clients and AppServer sessions can cause lock contention with each other as multiple database clients of the same database. (For more information on locks and lock contention, also known as deadlock, see OpenEdge Development: Progress 4GL Handbook .)

Thus, it is important when performing direct database access from both client and AppServer sessions that you avoid or otherwise manage the possibility that all of these sessions might concurrently access the same record. If they do, and you attempt to run a transaction that changes the record on either the client or the AppServer, the SHARE-LOCK held by each one will prevent the record from being changed, and ultimately the transaction from being committed. If the continued execution of both the client and any Application Sever session depends on the transaction being completed, then a deadlock occurs that prevents the entire application from continuing.

To avoid a deadlock, you can use the Lock Wait Timeout (-lkwtmo) startup parameter for both a Progress 4GL client and the AppServer session (specified as part of the srvrStartupParam property value in your AppServer properties file). This parameter sets a limited time that any Progress 4GL procedure must wait to continue execution because of a lock. For more information on this parameter, see OpenEdge Deployment: Startup Command and Parameter Reference . However, this is not a solution to any fundamental design problems that might avoid the conflict altogether, such as an application that does not conform to the OERA.

The OpenEdge Reference Architecture (OERA), the Progress Software Corp. guide for designing OpenEdge enterprise applications, avoids the problem of client-server lock contention completely. In an application whose design conforms to the OERA, a client never accesses the enterprise data source and thus can never have a deadlock with the AppServer. The data source is managed solely by the AppServer, which also manages all exchange of enterprise data with the client. For more information on the OERA, see OpenEdge Getting Started: OpenEdge Reference Architecture .

However, if you cannot redesign your application to avoid this type of lock contention, you can code as described in the following sections:

On the client

When a lock wait time out occurs on the AppServer because of a lock conflict that exceeds the time specified by the Lock Wait Timeout (-lkwtmo) startup parameter, a STOP condition is raised on the client side.

You cannot trap this stop condition simply by checking ERROR-STATUS:ERROR for a RUN statement that executes a remote procedure. The only way to handle this situation is to use the ON STOP phrase, as shown in this code fragment, as shown:

RUN testlkwtmo. 
MESSAGE RETURN-VALUE VIEW-AS ALERT-BOX INFO BUTTONS OK. 
PROCEDURE testlkwtmo: 
    DO ON STOP UNDO, RETURN "STOP occurred": 
        DEFINE VARIABLE flag AS LOGICAL    NO-UNDO. 
        DEFINE VAR sh AS HANDLE. /* Server handle */ 
        /* Invoke procedure on the server that locks records. */ 
        CREATE SERVER sh. 
        sh:CONNECT("-AppService asbroker1 -H localhost"). 
        RUN lockrecords.p ON SERVER sh (OUTPUT flag) NO-ERROR. 
        MESSAGE "flag :" flag SKIP "ERROR-STATUS:ERROR :" ERROR-STATUS:ERROR 
                VIEW-AS ALERT-BOX INFO BUTTONS OK. 
    END. 
END. 

If lockrecords.p terminates on the AppServer because of a lock wait time out, the AppServer raises a STOP condition on the client. The client program flow never reaches the message following the RUN statement that executes lockrecords.p, However, the client can catch the STOP condition and handle character string returned in RETURN-VALUE.

On the AppServer

On the AppServer, another technique for managing lock conflicts is to use the NO-WAIT and NO-ERROR options on any FIND statement that also applies an EXCLUSIVE-LOCK to the record. You can then test the resulting record buffer using the LOCKED function to detect a conflict:

FIND FIRST customer EXCLUSIVE-LOCK NO-WAIT NO-ERROR.
IF LOCKED customer THEN RETURN "customer,FIRST,LOCKED". 


Copyright © 2005 Progress Software Corporation
www.progress.com
Voice: (781) 280-4000
Fax: (781) 280-4095